local ffi = require("ffi");
if(ANDROID)then
    return nil;
end
local function lsoundWrite(ptr,stream,len)
    return 0;
end
local function lsoundInit(rate)
    return 1;
end
--关于声音的初始化
LsoundWrite = ffi.cast('int (*)(void*userdata,uint32_t *stream,int len)',lsoundWrite);
LsoundInit = ffi.cast('int (*)(int rate)',lsoundInit);
null = ffi.cast('void*',nil);
print(type(null));

ffi.cdef[[
typedef struct cSoundDriver{
    void* data;
    void (*free)(struct cSoundDriver*s);
    int (*init)(struct cSoundDriver*s);
    void (*pause)(struct cSoundDriver*s);
    void (*reset)(struct cSoundDriver*s);
    void (*resume)(struct cSoundDriver*s);
    void (*write)(struct cSoundDriver*s,uint16_t * finalWave, int length);
    void (*setThrottle)(unsigned short throttle);
}cSoundDriver;
struct cSoundDriver* (*CSoundInit)();
void (*ShowSpeed)(int f);
uint32_t (* GetTick)();
int emulating_get();

typedef struct gzFile_s gzFile_s;
typedef struct variable_desc variable_desc;
typedef size_t off_t;
typedef int IMAGE_TYPE;
typedef struct SoundDriver SoundDriver;

void CVBASet_systemGbPalette(int a1,int a2);
int CVBAGet_systemGbPalette(int a1);
void CVBASet_systemColorMap32(int a1,int a2);
int CVBAGet_systemColorMap32(int a1);
void CVBASet_systemColorMap16(int a1,int a2);
int CVBAGet_systemColorMap16(int a1);
int CVBASet_systemSaveUpdateCounter(int a1);
int CVBAGet_systemSaveUpdateCounter();
int CVBASet_systemFrameSkip(int a1);
int CVBAGet_systemFrameSkip();
int CVBASet_systemVerbose(int a1);
int CVBAGet_systemVerbose();
int CVBASet_systemColorDepth(int a1);
int CVBAGet_systemColorDepth();
int CVBASet_systemBlueShift(int a1);
int CVBAGet_systemBlueShift();
int CVBASet_systemGreenShift(int a1);
int CVBAGet_systemGreenShift();
int CVBASet_systemRedShift(int a1);
int CVBAGet_systemRedShift();
int CVBASet_IME(int a1);
int CVBAGet_IME();
int CVBASet_IF(int a1);
int CVBAGet_IF();
int CVBASet_IE(int a1);
int CVBAGet_IE();
int CVBASet_P1(int a1);
int CVBAGet_P1();
int CVBASet_TM3CNT(int a1);
int CVBAGet_TM3CNT();
int CVBASet_TM3D(int a1);
int CVBAGet_TM3D();
int CVBASet_TM2CNT(int a1);
int CVBAGet_TM2CNT();
int CVBASet_TM2D(int a1);
int CVBAGet_TM2D();
int CVBASet_TM1CNT(int a1);
int CVBAGet_TM1CNT();
int CVBASet_TM1D(int a1);
int CVBAGet_TM1D();
int CVBASet_TM0CNT(int a1);
int CVBAGet_TM0CNT();
int CVBASet_TM0D(int a1);
int CVBAGet_TM0D();
int CVBASet_DM3CNT_H(int a1);
int CVBAGet_DM3CNT_H();
int CVBASet_DM3CNT_L(int a1);
int CVBAGet_DM3CNT_L();
int CVBASet_DM3DAD_H(int a1);
int CVBAGet_DM3DAD_H();
int CVBASet_DM3DAD_L(int a1);
int CVBAGet_DM3DAD_L();
int CVBASet_DM3SAD_H(int a1);
int CVBAGet_DM3SAD_H();
int CVBASet_DM3SAD_L(int a1);
int CVBAGet_DM3SAD_L();
int CVBASet_DM2CNT_H(int a1);
int CVBAGet_DM2CNT_H();
int CVBASet_DM2CNT_L(int a1);
int CVBAGet_DM2CNT_L();
int CVBASet_DM2DAD_H(int a1);
int CVBAGet_DM2DAD_H();
int CVBASet_DM2DAD_L(int a1);
int CVBAGet_DM2DAD_L();
int CVBASet_DM2SAD_H(int a1);
int CVBAGet_DM2SAD_H();
int CVBASet_DM2SAD_L(int a1);
int CVBAGet_DM2SAD_L();
int CVBASet_DM1CNT_H(int a1);
int CVBAGet_DM1CNT_H();
int CVBASet_DM1CNT_L(int a1);
int CVBAGet_DM1CNT_L();
int CVBASet_DM1DAD_H(int a1);
int CVBAGet_DM1DAD_H();
int CVBASet_DM1DAD_L(int a1);
int CVBAGet_DM1DAD_L();
int CVBASet_DM1SAD_H(int a1);
int CVBAGet_DM1SAD_H();
int CVBASet_DM1SAD_L(int a1);
int CVBAGet_DM1SAD_L();
int CVBASet_DM0CNT_H(int a1);
int CVBAGet_DM0CNT_H();
int CVBASet_DM0CNT_L(int a1);
int CVBAGet_DM0CNT_L();
int CVBASet_DM0DAD_H(int a1);
int CVBAGet_DM0DAD_H();
int CVBASet_DM0DAD_L(int a1);
int CVBAGet_DM0DAD_L();
int CVBASet_DM0SAD_H(int a1);
int CVBAGet_DM0SAD_H();
int CVBASet_DM0SAD_L(int a1);
int CVBAGet_DM0SAD_L();
int CVBASet_COLY(int a1);
int CVBAGet_COLY();
int CVBASet_COLEV(int a1);
int CVBAGet_COLEV();
int CVBASet_BLDMOD(int a1);
int CVBAGet_BLDMOD();
int CVBASet_MOSAIC(int a1);
int CVBAGet_MOSAIC();
int CVBASet_WINOUT(int a1);
int CVBAGet_WINOUT();
int CVBASet_WININ(int a1);
int CVBAGet_WININ();
int CVBASet_WIN1V(int a1);
int CVBAGet_WIN1V();
int CVBASet_WIN0V(int a1);
int CVBAGet_WIN0V();
int CVBASet_WIN1H(int a1);
int CVBAGet_WIN1H();
int CVBASet_WIN0H(int a1);
int CVBAGet_WIN0H();
int CVBASet_BG3Y_H(int a1);
int CVBAGet_BG3Y_H();
int CVBASet_BG3Y_L(int a1);
int CVBAGet_BG3Y_L();
int CVBASet_BG3X_H(int a1);
int CVBAGet_BG3X_H();
int CVBASet_BG3X_L(int a1);
int CVBAGet_BG3X_L();
int CVBASet_BG3PD(int a1);
int CVBAGet_BG3PD();
int CVBASet_BG3PC(int a1);
int CVBAGet_BG3PC();
int CVBASet_BG3PB(int a1);
int CVBAGet_BG3PB();
int CVBASet_BG3PA(int a1);
int CVBAGet_BG3PA();
int CVBASet_BG2Y_H(int a1);
int CVBAGet_BG2Y_H();
int CVBASet_BG2Y_L(int a1);
int CVBAGet_BG2Y_L();
int CVBASet_BG2X_H(int a1);
int CVBAGet_BG2X_H();
int CVBASet_BG2X_L(int a1);
int CVBAGet_BG2X_L();
int CVBASet_BG2PD(int a1);
int CVBAGet_BG2PD();
int CVBASet_BG2PC(int a1);
int CVBAGet_BG2PC();
int CVBASet_BG2PB(int a1);
int CVBAGet_BG2PB();
int CVBASet_BG2PA(int a1);
int CVBAGet_BG2PA();
int CVBASet_BG3VOFS(int a1);
int CVBAGet_BG3VOFS();
int CVBASet_BG3HOFS(int a1);
int CVBAGet_BG3HOFS();
int CVBASet_BG2VOFS(int a1);
int CVBAGet_BG2VOFS();
int CVBASet_BG2HOFS(int a1);
int CVBAGet_BG2HOFS();
int CVBASet_BG1VOFS(int a1);
int CVBAGet_BG1VOFS();
int CVBASet_BG1HOFS(int a1);
int CVBAGet_BG1HOFS();
int CVBASet_BG0VOFS(int a1);
int CVBAGet_BG0VOFS();
int CVBASet_BG0HOFS(int a1);
int CVBAGet_BG0HOFS();
int CVBASet_BG3CNT(int a1);
int CVBAGet_BG3CNT();
int CVBASet_BG2CNT(int a1);
int CVBAGet_BG2CNT();
int CVBASet_BG1CNT(int a1);
int CVBAGet_BG1CNT();
int CVBASet_BG0CNT(int a1);
int CVBAGet_BG0CNT();
int CVBASet_VCOUNT(int a1);
int CVBAGet_VCOUNT();
int CVBASet_DISPSTAT(int a1);
int CVBAGet_DISPSTAT();
int CVBASet_DISPCNT(int a1);
int CVBAGet_DISPCNT();
int CVBASet_layerEnable(int a1);
int CVBAGet_layerEnable();
int CVBASet_layerSettings(int a1);
int CVBAGet_layerSettings();
int CVBASet_saveType(int a1);
int CVBAGet_saveType();
int CVBASet_stop(int a1);
int CVBAGet_stop();
int CVBASet_armMode(int a1);
int CVBAGet_armMode();
int CVBASet_armNextPC(int a1);
int CVBAGet_armNextPC();
int CVBASet_armIrqEnable(int a1);
int CVBAGet_armIrqEnable();
int CVBASet_armState(int a1);
int CVBAGet_armState();
int CVBASet_V_FLAG(int a1);
int CVBAGet_V_FLAG();
int CVBASet_Z_FLAG(int a1);
int CVBAGet_Z_FLAG();
int CVBASet_C_FLAG(int a1);
int CVBAGet_C_FLAG();
int CVBASet_N_FLAG(int a1);
int CVBAGet_N_FLAG();
void CVBASet_ioMem(void* a1);
void* CVBAGet_ioMem();
void CVBASet_oam(void* a1);
void* CVBAGet_oam();
void CVBASet_vram(void* a1);
void* CVBAGet_vram();
void CVBASet_paletteRAM(void* a1);
void* CVBAGet_paletteRAM();
void CVBASet_workRAM(void* a1);
void* CVBAGet_workRAM();
void CVBASet_internalRAM(void* a1);
void* CVBAGet_internalRAM();
void CVBASet_rom(void* a1);
void* CVBAGet_rom();
void CVBASet_bios(void* a1);
void* CVBAGet_bios();
void CVBASet_pix(void* a1);
void* CVBAGet_pix();
int CVBAemuGetEmuCount();
void CVBAemuUpdateCPSR();
bool CVBAemuWriteBMP(void* a1);
bool CVBAemuWritePNG(void* a1);
bool CVBAemuWriteMemState(void* a1,int a2,long int* a3);
bool CVBAemuReadMemState(void* a1,int a2);
bool CVBAemuWriteState(const char* a1);
bool CVBAemuReadState(const char* a1);
bool CVBAemuWriteBattery(void* a1);
bool CVBAemuReadBattery(void* a1);
void CVBAemuCleanUp();
void CVBAemuReset();
void CVBAemuMain(int a1);
void CutilWriteInt(gzFile_s* a1,int a2);
int CutilReadInt(gzFile_s* a1);
void CutilReadDataSkip(gzFile_s* a1,variable_desc* a2);
void CutilReadData(gzFile_s* a1,variable_desc* a2);
void CutilWriteData(gzFile_s* a1,variable_desc* a2);
long int CutilGzMemTell(gzFile_s* a1);
off_t CutilGzSeek(gzFile_s* a1,off_t a2,int a3);
int CutilGzClose(gzFile_s* a1);
int CutilGzRead(gzFile_s* a1,void* a2,unsigned int a3);
int CutilGzWrite(gzFile_s* a1,void* a2,unsigned int a3);
gzFile_s* CutilMemGzOpen(char* a1,int a2,const char* a3);
gzFile_s* CutilGzOpen(const char* a1,const char* a2);
bool CutilFileExists(const char* a1);
void CutilUpdateSystemColorMaps(bool a1);
void CutilGBAFindSave(const int a1);
void CutilPutWord(uint8_t* a1,uint16_t a2);
void CutilPutDword(uint8_t* a1,uint32_t a2);
void CutilExtract(const char* a1,const char* a2);
IMAGE_TYPE CutilFindType(const char* a1);
void CutilStripDoubleExtension(const char* a1,char* a2);
bool CutilIsZipFile(const char* a1);
bool CutilIsGzipFile(const char* a1);
bool CutilIsGBImage(const char* a1);
bool CutilIsGBAImage(const char* a1);
void CutilApplyIPS(const char* a1,uint8_t** a2,int* a3);
bool CutilWriteBMPFile(const char* a1,int a2,int a3,uint8_t* a4);
bool CutilWritePNGFile(const char* a1,int a2,int a3,uint8_t* a4);
void CutilReadScreenPixels(uint8_t* a1,int a2,int a3);
void CsoundReadGame(gzFile_s* a1,int a2);
void CsoundSaveGame(gzFile_s* a1);
void CsoundTimerOverflow(int a1);
void CsoundEvent(uint32_t a1,uint16_t a2);
void CsoundEvent(uint32_t a1,uint8_t a2);
void CsoundReset();
void CsoundSetSampleRate(long int a1);
long int CsoundGetSampleRate();
void CsoundShutdown();
void CsoundResume();
void CsoundPause();
int CsoundGetEnable();
void CsoundSetEnable(int a1);
float CsoundGetVolume();
void CsoundSetVolume(float a1);
void CsoundSetThrottle(short unsigned int a1);
bool CsoundInit();
bool CCPUIsZipFile(const char* a1);
bool CCPUIsGBAImage(const char* a1);
void CCPUCheckDMA(int a1,int a2);
void CCPULoop(int a1);
void CCPUReset();
void CCPUInit(const char* a1,bool a2);
void CCPUUpdateRegister(uint32_t a1,uint16_t a2);
//int CCPULoadRomData(const char* a1,int a2);
int CCPULoadRom(const char* a1);
bool CCPUWriteState(const char* a1);
bool CCPUReadState(const char* a1);
bool CCPUWriteMemState(char* a1,int a2);
bool CCPUReadMemState(char* a1,int a2);
void CCPUUpdateRenderBuffers(bool a1);
void CCPUUpdateRender();
void CCPUCleanUp();
bool CCPUWriteBMPFile(const char* a1);
bool CCPUWritePNGFile(const char* a1);
bool CCPUImportEepromFile(const char* a1);
bool CCPUExportEepromFile(const char* a1);
bool CCPUReadBatteryFile(const char* a1);
bool CCPUWriteBatteryFile(const char* a1);
bool CCPUWriteGSASnapshot(const char* a1,const char* a2,const char* a3,const char* a4);
bool CCPUReadGSASPSnapshot(const char* a1);
bool CCPUReadGSASnapshot(const char* a1);
void CsystemGbBorderOn();
void CsystemFrame();
void Csystem10Frames(int a1);
void CsystemShowSpeed(int a1);
bool CsystemCanChangeSoundQuality();
void CsystemPossibleCartridgeRumble(bool a1);
void CsystemCartridgeRumble(bool a1);
uint8_t CsystemGetSensorDarkness();
int CsystemGetSensorZ();
int CsystemGetSensorY();
int CsystemGetSensorX();
void CsystemUpdateMotionSensor();
void CsystemScreenMessage(const char* a1);
void CsystemOnSoundShutdown();
void CsystemOnWriteDataToSoundBuffer(const uint16_t* a1,int a2);
SoundDriver* CsystemSoundInit();
void CsystemSetTitle(const char* a1);
void CsystemMessage(int a1,const char* a2);
uint32_t CsystemGetClock();
uint32_t CsystemReadJoypad(int a1);
bool CsystemReadJoypads();
void CsystemDrawScreen();
void CsystemScreenCapture(int a1);
void CsystemGbPrint(uint8_t* a1,int a2,int a3,int a4,int a5,int a6);
bool CsystemPauseOnFrame();
extern int key;
]];

local vbam = loadso('vbam');


function SoundDriver()
    --local soundptr = ffi.new('cSoundDriver[1]'); --可能会被垃圾回收
    local soundptr = ffi.cast('cSoundDriver*',calloc(ffi.sizeof('cSoundDriver'),1));
    local sound = soundptr[0];
    local wave = {
        data = nil,
        len = 0
    }
    local s = CreateSound(
    function(userdata,stream,len)
        --混合声音
        --print(1112);
        --print('aaasdf',userdata,len,stream);
        -- if(len>wave.len)then len = wave.len; end;
        -- if(len>0)then
        --     ffi.copy(stream,wave.data,len);
        -- end
    end
    );
    sound.init = function(data)
        return 1;
    end
    sound.pause = function(data)
    end
    sound.reset = function(data)
    end
    sound.resume = function(data)
    end
    sound.write = function(data,wave_data,len)
        s:WriteWave(wave_data,len);
    end
    sound.setThrottle = function(data,throttle)

    end
    
    return soundptr;
end

local init = nil;
function LoadROM(fn)
    local self = {};
    if(init==nil)then
        --lvbam = ffi.load('lvbam');
        vbam.CSoundInit = SoundDriver;
        vbam.GetTick = GetTick;
        vbam.ShowSpeed = function(f)
            self.speed = f;
        end
    end
    print('load',vbam.CCPULoadRom(fn));


    --初始化颜色
    -- VBASet_systemRedShift(19)
    -- VBASet_systemGreenShift(11)
    -- VBASet_systemBlueShift(3)
    -- utilUpdateSystemColorMaps(0);
    vbam.CVBASet_systemRedShift(19);
    vbam.CVBASet_systemGreenShift(11)
    vbam.CVBASet_systemBlueShift(3)
    vbam.CutilUpdateSystemColorMaps(0);

    --初始化声音
    print("init",vbam.CsoundInit());
    vbam.CsoundSetSampleRate(44100);

    --重置
    vbam.CCPUInit(nil,0);

    vbam.CCPUReset();
    vbam.CsoundReset();




    --设置跳帧
    --VBASet_systemFrameSkip(1);
    local pix = vbam.CVBAGet_pix();
    self.pix = pix;
    function self:main()
        if(self.draw~=nil)then
            self:draw(self.pix,240,160,32);
        end
        local tick = vbam.CVBAemuGetEmuCount();
        --print("emu",lvbam.emulating_get());
        vbam.CVBAemuMain(tick);
    end

    function self:SetKey(key)
        vbam.key = key;
    end

    function self:gameSpeed()
        return self.speed;
    end

    function self:SaveState(fn)
        vbam.CVBAemuWriteState(fn);
    end

    function self:LoadState(fn)
        vbam.CVBAemuReadState(fn);
    end

    return self;
end

return {
    LoadROM = LoadROM,
}

